// PR c++/110344
// { dg-do compile { target c++26 } }
// { dg-skip-if "requires hosted libstdc++ for cwchar" { ! hostedlib } }

#include <string_view>
struct Sheep {
  constexpr std::string_view speak() const noexcept { return "Baaaaaa"; }
};
struct Cow {
  constexpr std::string_view speak() const noexcept { return "Mooo"; }
};
class Animal_View {
private:
  const void *animal;
  std::string_view (*speak_function)(const void *);
public:
  template <typename Animal>
  constexpr Animal_View(const Animal &a)
    : animal{&a}, speak_function{[](const void *object) {
				   return static_cast<const Animal *>(object)->speak();
				 }} {}
  constexpr std::string_view speak() const noexcept {
    return speak_function(animal);
  }
};
// This is the key bit here. This is a single concrete function
// that can take anything that happens to have the "Animal_View"
// interface
constexpr std::string_view do_speak(Animal_View av) { return av.speak(); }
int main() {
  // A Cow is a cow. The only think that makes it special
  // is that it has a "std::string_view speak() const" member
  constexpr Cow cow;
  constexpr auto result = do_speak(cow);
  return static_cast<int>(result.size());
}
